﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MapGenerator
{
    public partial class Form1 : Form
    {
        List<List<int>> mapGrid;
        int sizeX, sizeY;
        int cellSize = 20;
        int curXPosition, curYPosition;
        int startPosX, startPosY;
        Random rnd;

        public Form1()
        {
            InitializeComponent();
            rnd = new Random();
            startPosX = startPosY = -1;
            InitializeMapGrid();
            UpdateMapGrid();
            curXPosition = curYPosition = -2;
        }

        private void quitterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void UpdateMapGrid()
        {
            pbMapGrid.Refresh();
        }

        private void pbMapGrid_Paint(object sender, PaintEventArgs e)
        {
            try
            {
                Graphics g = e.Graphics;

                Pen p = new Pen(Color.Black, 2);
                pbMapGrid.Size = new Size((cellSize + 2) * (sizeX), (cellSize + 2) * (sizeY));

                Font font = new Font("Arial", 10.0f);
                for (int y = 0; y < sizeY + 2; ++y)
                {
                    g.DrawLine(p, 0, y * cellSize, (sizeX + 1) * cellSize, y * cellSize);
                    g.DrawString((y-1).ToString(), font, Brushes.Black, new Point(0, y * cellSize));
                }
                for (int x = 0; x < sizeX + 2; ++x)
                {
                    g.DrawLine(p, x * cellSize, 0, x * cellSize, (sizeY + 1) * cellSize);
                    g.DrawString((x-1).ToString(), font, Brushes.Black, new Point(x * cellSize, 0));
                }

                SolidBrush grayBrush = new SolidBrush(Color.Gray); //Rue(vide)
                SolidBrush blueBrush = new SolidBrush(Color.CornflowerBlue); //Building 1
                SolidBrush brownBrush = new SolidBrush(Color.Peru); //Building 2
                SolidBrush greenBrush = new SolidBrush(Color.Green); //Building 3
                SolidBrush orangeBrush = new SolidBrush(Color.Orange); //Building 4
                SolidBrush turquoiseBrush = new SolidBrush(Color.Turquoise); //Building 5
                SolidBrush purpleBrush = new SolidBrush(Color.MediumOrchid); //Building 6
                SolidBrush salmonBrush = new SolidBrush(Color.Salmon); //Building 7
                SolidBrush darkKhakiBrush = new SolidBrush(Color.DarkKhaki); //Building 8
                SolidBrush deepPinkBrush = new SolidBrush(Color.DeepPink); //Building 9
                SolidBrush khakiBrush = new SolidBrush(Color.Khaki); //Building 10
                SolidBrush paleGreenBrush = new SolidBrush(Color.PaleGreen); //Building 11
                SolidBrush pinkBrush = new SolidBrush(Color.Pink); //Building 12
                SolidBrush yellowBrush = new SolidBrush(Color.Yellow); //Obstacle
                SolidBrush redBrush = new SolidBrush(Color.Red); //Obstacle Indestructible
                SolidBrush peachBrush = new SolidBrush(Color.PeachPuff); //Passants
                SolidBrush whiteBrush = new SolidBrush(Color.White); //Rue part 1
                SolidBrush blackBrush = new SolidBrush(Color.Black); //Rue part 1

                int col;
                int lineSize = 6;
                Rectangle rectangle;
                Rectangle circle;
                for(int row = 0; row < sizeY; ++row)
                {
                    for (col = 0; col < sizeX; ++col)
                    {
                        rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1, cellSize - 2, cellSize - 2);
                        switch(mapGrid[row][col])
                        {
                            case -1: //StartPos
                                g.FillRectangle(redBrush, rectangle);
                                startPosX = col;
                                startPosY = row;
                                break;
                            case 0: //Rue (vide)                     
                                g.FillRectangle(grayBrush, rectangle);
                                break;
                            case 1: //Building 1
                                g.FillRectangle(blueBrush, rectangle);
                                break;
                            case 2: //Building 2
                                g.FillRectangle(brownBrush, rectangle);
                                break;
                            case 3: //Building 3
                                g.FillRectangle(greenBrush, rectangle);
                                break;
                            case 4: //Building 4
                                g.FillRectangle(orangeBrush, rectangle);
                                break;
                            case 5: //Building 5
                                g.FillRectangle(turquoiseBrush, rectangle);
                                break;
                            case 6: //Building 6
                                g.FillRectangle(purpleBrush, rectangle);
                                break;
                            case 7: //Building 7
                                g.FillRectangle(salmonBrush, rectangle);
                                break;
                            case 8: //Building 8
                                g.FillRectangle(darkKhakiBrush, rectangle);
                                break;
                            case 9: //Building 9
                                g.FillRectangle(deepPinkBrush, rectangle);
                                break;
                            case 10: //Building 10
                                g.FillRectangle(khakiBrush, rectangle);
                                break;
                            case 11: //Building 11
                                g.FillRectangle(paleGreenBrush, rectangle);
                                break;
                            case 12: //Building 12
                                g.FillRectangle(pinkBrush, rectangle);
                                break;
                            case 13: //Rue 1
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1 + (cellSize - lineSize - 1), cellSize - 2, lineSize);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 14: //Rue 2
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1, cellSize - 2, lineSize);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 15: //Rue 3
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1 + (cellSize - lineSize - 1), ((row + 1) * cellSize) + 1, lineSize, cellSize - 2);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 16: //Rue 4
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1, lineSize, cellSize - 2);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 17: //Rue 5
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1, cellSize - 2, lineSize);
                                g.FillRectangle(blackBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1, lineSize, cellSize - 2);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 18: //Rue 6
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1, lineSize, cellSize - 2);
                                g.FillRectangle(blackBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1 + (cellSize - lineSize - 1), cellSize - 2, lineSize);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 19: //Rue 7
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1, cellSize - 2, lineSize);
                                g.FillRectangle(blackBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1 + (cellSize - lineSize - 1), ((row + 1) * cellSize) + 1, lineSize, cellSize - 2);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 20: //Rue 8
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1 + (cellSize - lineSize - 1), ((row + 1) * cellSize) + 1, lineSize, cellSize - 2);
                                g.FillRectangle(blackBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1 + (cellSize - lineSize - 1), cellSize - 2, lineSize);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 21: //Rue 9
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1 + (cellSize - lineSize - 1), ((row + 1) * cellSize) + 1 + (cellSize - lineSize - 1), lineSize, lineSize);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 22: //Rue 10
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1 + (cellSize - lineSize - 1), ((row + 1) * cellSize) + 1, lineSize, lineSize);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 23: //Rue 11
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1 + (cellSize - lineSize - 1), lineSize, lineSize);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 24: //Rue 12
                                g.FillRectangle(whiteBrush, rectangle);
                                rectangle = new Rectangle(((col + 1) * cellSize) + 1, ((row + 1) * cellSize) + 1, lineSize, lineSize);
                                g.FillRectangle(blackBrush, rectangle);
                                break;
                            case 25: //Obstacle
                                g.FillRectangle(grayBrush, rectangle);
                                circle = new Rectangle(((col + 1) * cellSize) + (int)Math.Ceiling(cellSize / 4.0), ((row + 1) * cellSize) + (int)Math.Ceiling(cellSize / 4.0), cellSize - (int)Math.Ceiling(cellSize / 2.0), cellSize - (int)Math.Ceiling(cellSize / 2.0));
                                g.FillEllipse(yellowBrush, circle);
                                break;
                            case 26: //Obstacle Indestructible
                                g.FillRectangle(grayBrush, rectangle);
                                circle = new Rectangle(((col + 1) * cellSize) + (int)Math.Ceiling(cellSize / 4.0), ((row + 1) * cellSize) + (int)Math.Ceiling(cellSize / 4.0), cellSize - (int)Math.Ceiling(cellSize / 2.0), cellSize - (int)Math.Ceiling(cellSize / 2.0));
                                g.FillEllipse(redBrush, circle);
                                break;
                            case 27: //Passants
                                g.FillRectangle(grayBrush, rectangle);
                                circle = new Rectangle(((col + 1) * cellSize) + (int)Math.Ceiling(cellSize / 4.0), ((row + 1) * cellSize) + (int)Math.Ceiling(cellSize / 4.0), cellSize - (int)Math.Ceiling(cellSize / 2.0), cellSize - (int)Math.Ceiling(cellSize / 2.0));
                                g.FillEllipse(peachBrush, circle);
                                break;
                        }
                    }
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine("{0} Exception caught.", ex);
            }
        }

        private void pbMapGrid_MouseClick(object sender, MouseEventArgs e)
        {
            Point p1 = pbMapGrid.PointToClient(Cursor.Position);
            int col = (int)(p1.X / (cellSize)) - 1;
            int row = (int)(p1.Y / (cellSize)) - 1;
            lPosition.Text = "( " + col.ToString() + ", " + row.ToString() + ")";
            ClickUpdate(col, row);
        }

        private int ClickUpdate(int col, int row)
        {
            if ((col < sizeX) && (col >= 0) && (row < sizeY) && (row >= 0))
            {
                if (!rbAucun.Checked)
                {
                    if (mapGrid[row][col] == -1)
                    {
                        startPosX = startPosY = -1;
                    }
                    if(rbStartPos.Checked)
                    {
                        mapGrid[row][col] = -1;
                        if(startPosX != -1)
                        {
                            mapGrid[startPosY][startPosX] = 0;
                        }
                        startPosX = col;
                        startPosY = row;
                        rbAucun.Checked = true;
                    }
                    else if (rbVide.Checked)
                    {
                        mapGrid[row][col] = 0;
                    }
                    else if (rbBatiment1.Checked)
                    {
                        mapGrid[row][col] = 1;
                    }
                    else if (rbBatiment2.Checked)
                    {
                        mapGrid[row][col] = 2;
                    }
                    else if (rbBatiment3.Checked)
                    {
                        mapGrid[row][col] = 3;
                    }
                    else if (rbBatiment4.Checked)
                    {
                        mapGrid[row][col] = 4;
                    }
                    else if (rbBatiment5.Checked)
                    {
                        mapGrid[row][col] = 5;
                    }
                    else if (rbBatiment6.Checked)
                    {
                        mapGrid[row][col] = 6;
                    }
                    else if (rbBatiment7.Checked)
                    {
                        mapGrid[row][col] = 7;
                    }
                    else if (rbBatiment8.Checked)
                    {
                        mapGrid[row][col] = 8;
                    }
                    else if (rbBatiment9.Checked)
                    {
                        mapGrid[row][col] = 9;
                    }
                    else if (rbBatiment10.Checked)
                    {
                        mapGrid[row][col] = 10;
                    }
                    else if (rbBatiment11.Checked)
                    {
                        mapGrid[row][col] = 11;
                    }
                    else if (rbBatiment12.Checked)
                    {
                        mapGrid[row][col] = 12;
                    }
                    else if (rbRue1.Checked)
                    {
                        mapGrid[row][col] = 13;
                    }
                    else if (rbRue2.Checked)
                    {
                        mapGrid[row][col] = 14;
                    }
                    else if (rbRue3.Checked)
                    {
                        mapGrid[row][col] = 15;
                    }
                    else if (rbRue4.Checked)
                    {
                        mapGrid[row][col] = 16;
                    }
                    else if (rbRue5.Checked)
                    {
                        mapGrid[row][col] = 17;
                    }
                    else if (rbRue6.Checked)
                    {
                        mapGrid[row][col] = 18;
                    }
                    else if (rbRue7.Checked)
                    {
                        mapGrid[row][col] = 19;
                    }
                    else if (rbRue8.Checked)
                    {
                        mapGrid[row][col] = 20;
                    }
                    else if (rbRue9.Checked)
                    {
                        mapGrid[row][col] = 21;
                    }
                    else if (rbRue10.Checked)
                    {
                        mapGrid[row][col] = 22;
                    }
                    else if (rbRue11.Checked)
                    {
                        mapGrid[row][col] = 23;
                    }
                    else if (rbRue12.Checked)
                    {
                        mapGrid[row][col] = 24;
                    }
                    else if (rbObstacle.Checked)
                    {
                        mapGrid[row][col] = 25;
                    }
                    else if (rbObstacleIndestructible.Checked)
                    {
                        mapGrid[row][col] = 26;
                    }
                    else if (rbPassant.Checked)
                    {
                        mapGrid[row][col] = 27;
                    }
                    else if (rbBatimentRandom.Checked)
                    {
                        mapGrid[row][col] = rnd.Next(1, 13);
                    }
                    UpdateMapGrid(); 
                    return mapGrid[row][col];
                }
            }
            return 0;
        }

        private void InitializeMapGrid()
        {
            sizeX = (int)nUDCols.Value;
            sizeY = (int)nUDRows.Value;
            lSize.Text = "( " + sizeX.ToString() + ", " + sizeY.ToString() + ")";
            int x,y;
            List<int> colList;
            mapGrid = new List<List<int>>();
            for(y = 0; y < sizeY; ++y)
            {
                colList = new List<int>();
                for (x = 0; x < sizeX; ++x)
                {
                    colList.Add(0);
                }
                mapGrid.Add(colList);
            }
        }

        private void btNewMap_Click(object sender, EventArgs e)
        {
            string message = "Êtes vous certain de vouloir écraser la carte présente?";
            string caption = "Êtes-vous certain?";
            MessageBoxButtons buttons = MessageBoxButtons.YesNo;
            // Displays the MessageBox.
            DialogResult result = MessageBox.Show(message, caption, buttons);

            if (result == System.Windows.Forms.DialogResult.Yes)
            {
                InitializeMapGrid();
                UpdateMapGrid();
            }
        }

        private void btGenerateMapText_Click(object sender, EventArgs e)
        {
            Save form = new Save(mapGrid);
            form.ShowDialog();
        }

        private void btChargerCodeCarte_Click(object sender, EventArgs e)
        {
            Load form = new Load();
            form.ShowDialog();
            if(form.mapGrid != null && form.mapGrid.Count != 0)
            {
                mapGrid = form.mapGrid;
                UpdateMapGrid();
            }
        }

        private void exporterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Save form = new Save(mapGrid);
            form.ShowDialog();
        }

        private void importerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Load form = new Load();
            form.ShowDialog();
            if (form.mapGrid.Count != 0)
            {
                mapGrid = form.mapGrid;
                UpdateMapGrid();
            }
        }

        private void pbMapGrid_MouseMove(object sender, MouseEventArgs e)
        {
            if (pbMapGrid.ClientRectangle.Contains(pbMapGrid.PointToClient(Control.MousePosition)))
            {
                if (e.Button == MouseButtons.Left)
                {
                    Point p1 = pbMapGrid.PointToClient(Cursor.Position);
                    int col = (int)(p1.X / (cellSize)) - 1;
                    int row = (int)(p1.Y / (cellSize)) - 1;
                    lPosition.Text = "( " + col.ToString() + ", " + row.ToString() + ")";
                    if ((col != curXPosition) || (row != curXPosition))
                    {
                        curXPosition = col;
                        curYPosition = row;
                        ClickUpdate(col, row);
                    }
                }
                else
                {
                    curXPosition = curYPosition = -2;
                }
            }
        }

        private void btRandomBuildings_Click(object sender, EventArgs e)
        {
            const int MIN = 1;
            const int MAX = 12;
            int col;
            for (int row = 0; row < sizeY; ++row)
            {
                for (col = 0; col < sizeX; ++col)
                {
                    if((mapGrid[row][col] >= 1) && (mapGrid[row][col] <= MAX))
                    {
                        mapGrid[row][col] = rnd.Next(MIN, MAX + 1);
                    }
                }
            }
            UpdateMapGrid();
        }

        private void btFill_Click(object sender, EventArgs e)
        {
            string message = "Êtes vous certain de vouloir écraser la carte présente?";
            string caption = "Êtes-vous certain?";
            MessageBoxButtons buttons = MessageBoxButtons.YesNo;
            // Displays the MessageBox.
            DialogResult result = MessageBox.Show(message, caption, buttons);

            if (result == System.Windows.Forms.DialogResult.Yes)
            {
                int col;
                int type = ClickUpdate(0, 0);
                for (int row = 0; row < sizeY; ++row)
                {
                    for (col = 0; col < sizeX; ++col)
                    {
                        mapGrid[row][col] = type;
                    }
                }
                UpdateMapGrid();
            }
        }
    }
}
